/**
 * 腾讯 cos 文件存储方法类封装
 */
import TencentCOS from 'cos-nodejs-sdk-v5';
import fs from 'fs';
import https from 'https';
import http from 'http';
import { TENCENT_COS_CONFIG } from '../config';

interface UploadOptions {
  Bucket?: string; // 空间名称
  Key?: string; // 文件名称,
  Body: any; // 文件内容，可以是路径名称或者文件流
  ContentLength?: number; // 文件大小，传入文件流需要传入文件大小
  Type?: string; // 传入的文件类型，filepath 或者 stream 或者 image-url
  useCdn?: boolean; // 是否使用 cdn 加速
  debug?: boolean; // 是否开启调试
}

const cosInstance = new TencentCOS({
  SecretId: TENCENT_COS_CONFIG.secretId,
  SecretKey: TENCENT_COS_CONFIG.secretKey
  // 可选参数
  // FileParallelLimit: 3, // 控制文件上传并发数
  // ChunkParallelLimit: 8, // 控制单个文件下分片上传并发数，在同园区上传可以设置较大的并发数
  // ChunkSize: 1024 * 1024 * 8, // 控制分片大小，单位 B，在同园区上传可以设置较大的分片大小
  // Proxy: '',
  // Protocol: 'http:',
  // 更多参数请参考: https://cloud.tencent.com/document/product/436/8629
});

/**
 * nodejs 将图片地址转化成 stream
 * @param options
 */
// eslint-disable-next-line
export function transImageUrlToBuffer(img) {
  if (!img) return null;
  return new Promise((resolve, reject) => {
    const request = img.indexOf('https') > -1 ? https : http;
    request.get(img, imgRes => {
      let chunks = []; // 用于保存网络请求不断加载传输的缓冲数据
      let size = 0; // 保存缓冲数据的总长度
      imgRes.on('data', chunk => {
        /**
         * 在进行网络请求时，会不断接收到数据(数据不是一次性获取到的)
         * node会把接收到的数据片段逐段的保存在缓冲区（Buffer）
         * 这些数据片段会形成一个个缓冲对象（即Buffer对象）
         * 而Buffer数据的拼接并不能像字符串那样拼接（因为一个中文字符占三个字节），
         * 如果一个数据片段携带着一个中文的两个字节，下一个数据片段携带着最后一个字节，
         * 直接字符串拼接会导致乱码，为避免乱码，所以将得到缓冲数据推入到chunks数组中，
         * 利用下面的node.js内置的Buffer.concat()方法进行拼接
         */
        // @ts-ignore
        chunks.push(chunk);
        size += chunk.length;
      });
      imgRes.on('end', err => {
        if (err) {
          reject(err);
          return;
        }
        const buffer = Buffer.concat(chunks, size);
        // 判断是否是一个buffer对象
        if (Buffer.isBuffer(buffer)) {
          resolve(buffer);
        } else {
          reject('trans image to buffer error');
        }
      });
    });
  });
}

/**
 * 上传文件到腾讯 Cos
 * @param options {UploadOptions} 上传参数
 */
async function uploadToTencentCos(options: UploadOptions) {
  const newOptions = {
    ...TENCENT_COS_CONFIG.fileServer.picture,
    Key: `tmpfile-${Date.now()}`,
    type: 'filepath',
    ...options
  };

  if (newOptions.Bucket === 'picture') {
    newOptions.Bucket = TENCENT_COS_CONFIG.fileServer.picture.Bucket;
    newOptions.Region = TENCENT_COS_CONFIG.fileServer.picture.Region;
  } else if (newOptions.Bucket === 'audio') {
    newOptions.Bucket = TENCENT_COS_CONFIG.fileServer.audio.Bucket;
    newOptions.Region = TENCENT_COS_CONFIG.fileServer.audio.Region;
  }

  if (newOptions.Type === 'filepath') {
    newOptions.Body = fs.readFileSync(newOptions.Body);
  } else if (newOptions.Type === 'buffer') {
    // newOptions.Body = newOptions.Body;
    newOptions.ContentLength = newOptions.Body.poolSize;
  } else if (newOptions.Type === 'image-url') {
    newOptions.Body = await transImageUrlToBuffer(newOptions.Body);
    newOptions.ContentLength = newOptions.Body.poolSize;
  } else if (newOptions.Type === 'base64') {
    newOptions.Body = Buffer.from(newOptions.Body.replace('data:image/png;base64,', '').replace('data:image/jpeg;base64,', ''), 'base64');
    newOptions.ContentLength = newOptions.Body.poolSize;
  }

  return new Promise((resolve, reject) => {
    cosInstance.putObject(
      {
        ...newOptions,
        onProgress: function (progressData) {
          newOptions.debug && console.log(JSON.stringify(progressData));
        }
      },
      function (err, data) {
        if (err) {
          reject(err);
        } else {
          if (newOptions.useCdn) {
            resolve(`https://${data.Location.replace('picture-1256514897.cos.ap-shanghai.myqcloud.com', 'picture-1256514897.file.myqcloud.com')}`);
          } else {
            resolve(`https://${data.Location}`);
          }
        }
      }
    );
  });
}

export default uploadToTencentCos;
